[% setvar title Objects: Autoaccessors for object data structures %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='TITLE'></a><h1>TITLE</h1>
<p>Objects: Autoaccessors for object data structures</p>
<a name='VERSION'></a><h1>VERSION</h1>
<pre>  Maintainer: Nathan Wiger &lt;<a href='mailto:nate@wiger.org'>nate@wiger.org</a>&gt;
  Date: 25 Aug 2000
  Last Modified: 29 Sep 2000
  Mailing List: <a href='mailto:perl6-language-objects@perl.org'>perl6-language-objects@perl.org</a>
  Number: 163
  Version: 3
  Status: Frozen
  Original Author: James Mastros &lt;<a href='mailto:james@rtweb.net'>james@rtweb.net</a>&gt;
  Requires: RFC 279, RFC 337</pre>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>This RFC proposes three attributes, <code>:laccess</code>, <code>:raccess</code>, and
<code>:roacess</code>, which when used on a blessed object variable,
automatically construct an <code>lvalue</code>, <code>rvalue</code>, or readonly
<code>rvalue</code> autoaccessor, respectively.</p>
<a name='NOTES ON FREEZE'></a><h1>NOTES ON FREEZE</h1>
<p>Pretty much everyone liked the basic idea, but the implementation needs
some work. In particular, Michael Schwern pointed out that using
attributes to declare these may not be the best method.  <b>RFC 337</b>
proposes a use of attributes that would allow them to basically act as
specialized subs, so this concern may be solved. Regardless, it is an
issue that needs revisiting; a package-wide pragma may be the best
solution.</p>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<a name='Overview'></a><h2>Overview</h2>
<p>Currently, to hide your data - even simply - you must create subs that
often look something like this:</p>
<pre>   sub fullname {
       my $self = shift;
       @_ ? $self-&gt;{fullname} = $_[0]
          : $self-&gt;{fullname};
   }</pre>
<p>This allows you to compartmentalize your data so that people can then
use it in their programs as:</p>
<pre>   $r-&gt;fullname('Nathan Wiger');
   print $r-&gt;fullname;</pre>
<p>For one or two data pieces, this is ok. But for lots of data, this chews
up a lot of time and code space unnecessarily.</p>
<p>This RFC proposes the attributes <code>:laccess</code>, <code>:raccess</code>, and
$<code>:roaccess</code> which would automate this process. The tags are kept
intentionally separate so that you can manually create an <code>rvalue</code> sub,
but use the attribute to generate an <code>lvalue</code> sub, or vice-versa.</p>
<a name='The :raccess attribute'></a><h2>The :raccess attribute</h2>
<p>We'll start with the &quot;easy one&quot;, which simply constructs an <code>rvalue</code>
sub. Consider this code:</p>
<pre>   package Bob;
   sub new {
       my $class = shift;
       my $self = {};
       $self-&gt;{name} :raccess = undef;
       $self-&gt;{age}  :raccess = undef;
       return bless $self, $class;
   }</pre>
<p>Basically, two new <code>rvalue</code> class methods would be created
automagically:</p>
<pre>   sub name {
       my $self = shift;
       @_ ? $self-&gt;{name} = $_[0]
          : $self-&gt;{name};
   }

   sub age {     
       my $self = shift;
       @_ ? $self-&gt;{age} = $_[0]
          : $self-&gt;{age};
   }</pre>
<p>These two subs could now be used in any <code>rvalue</code> context by anyone who
used your class:</p>
<pre>   my $jim = new Bob;
   $jim-&gt;name('Joe');
   $jim-&gt;age(42);
   print $jim-&gt;age;</pre>
<p>The benefits are obvious: It's quick and easy, especially if you just
need a simple data wrapper.</p>
<a name='The :roaccess attribute'></a><h2>The :roaccess attribute</h2>
<p>This works identically to the above sub, with the difference that
modification of its value is not allowed; it is readonly. As such,
the following:</p>
<pre>   $self-&gt;{name} :roaccess = &quot;Nate&quot;;</pre>
<p>Would create the equivalent of the following sub:</p>
<pre>   sub name {
       my $self = shift;
       croak &quot;Attempt to assign to readonly rvalue autoaccessor&quot; if @_;
       return $self-&gt;{name};
   }</pre>
<p>As such, you could fetch values but not set them:</p>
<pre>   print $r-&gt;name;     # &quot;Nate&quot;;
   $r-&gt;name('Jim');    # oops!</pre>
<p>The second one should result in an exception being thrown.</p>
<a name='The :laccess attribute'></a><h2>The :laccess attribute</h2>
<p>This tag works just like the above, only creating an <code>lvalue</code> sub
instead. So this code:</p>
<pre>   package JimmyHat;
   sub new {
       my $class = shift;
       my $self = {};
       $self-&gt;{size} :laccess = undef;
       return bless $self, $class;
   }</pre>
<p>Would basically create the following <code>lvalue</code> sub:</p>
<pre>   sub size : lvalue {
       shift-&gt;{size};
   }   </pre>
<p>Which could be used in any <code>lvalue</code> context:</p>
<pre>   my $raincoat = new JimmyHat;
   $raincoat-&gt;size = 42;
   $raincoat-&gt;size++;</pre>
<p>Easy enough.</p>
<a name='Specifying the name of the sub'></a><h2>Specifying the name of the sub</h2>
<p>The above cases are fine for simple situations, but often you will have
nested data structures. No fear, you can optionally specify the name of
the sub as an argument to the tag:</p>
<pre>   package Johnson;
   sub new {
       my $class = shift;
       my $self = {};
       $self-&gt;{DATA}-&gt;{NUMERIC}-&gt;{S_size} :raccess('size') = undef;
       $self-&gt;{DATA}-&gt;{STRING}-&gt;{PL_name} :laccess('name') = undef;
       return bless $self, $class;
   }</pre>
<p>This would basically have the effect of creating the following two subs:</p>
<pre>   sub size {
       my $self = shift;
       @_ ? $self-&gt;{DATA}-&gt;{NUMERIC}-&gt;{S_size} = $_[0]
          : $self-&gt;{DATA}-&gt;{NUMERIC}-&gt;{S_size}
   }

   sub name : lvalue {
       shift-&gt;{DATA}-&gt;{STRING}-&gt;{PL_name};
   }</pre>
<p>Which again, can be used in the appropriate contexts. Note this allows
you to maintain arrayref objects automatically as well:</p>
<pre>   package Johnson;
   sub new {
       my $class = shift;
       my $self = [];
       $self-&gt;[0]-&gt;[2]-&gt;[3] :raccess('size') = undef;
       $self-&gt;[4]-&gt;[1] :laccess('name') = undef;
       return bless $self, $class;
   }</pre>
<p>Although an arrayref is usually not the best data representation for
direct-access objects.</p>
<a name='Combining attributes'></a><h2>Combining attributes</h2>
<p>You can, of course, combine the <code>:laccess</code> and <code>:raccess</code> attributes
on a given key to autogenerate accessors that work in both <code>lvalue</code> and
<code>rvalue</code> contexts, if you simply want to hide your data.</p>
<p>The <code>:roaccess</code> can only be combined with the <code>:laccess</code> tag. In fact,
the <code>:roaccess</code> should probably <b>not</b> be combinable with any other
tag, but this RFC does not require this.</p>
<a name='Mixing autoaccessors and real subs'></a><h2>Mixing autoaccessors and real subs</h2>
<p>The final case is where these become really powerful, but also makes the
implementation a little tricky. Here, we want to create an lvalue sub
that does something productive, but an rvalue autoaccessor:</p>
<pre>   package 3rdLeg;
   sub new {
       my $class = shift;
       my $self = {};
       $self-&gt;{State}-&gt;{leg} :raccess = undef;
       return bless $self, $class;
   }

   sub leg : lvalue { 
       my $self = shift;
       # do a whole bunch of stuff ...
       $self-&gt;{State}-&gt;{leg};
   }</pre>
<p>This would autogenerate an <code>rvalue</code> autoaccessor for accessing <code>leg</code>,
but would then use the sub that you had explicitly declared as the
<code>lvalue</code> sub for <code>leg</code>.</p>
<a name='IMPLEMENTATION'></a><h1>IMPLEMENTATION</h1>
<p>In order for this to work, a couple things have to be true:</p>
<pre>   1. Autoaccessor methods have to take precedence over declared
      methods in some way.

   2. A means for duplication of method namespace has to exist.

   3. The autoaccessor tags :laccess and :raccess must dictate
      that autoaccessors be declared for *only* that context;
      this is different from the meaning of lvalue subs which 
      can be used in either.

   4. There must be a way to set attributes on individual hash keys
      in Perl 6. See RFC 279 and RFC 337.</pre>
<p>Note that throughout the RFC it has looked like this is a simple
sub-wrapper proposal, but it's not. As James Mastros (the original
author) said:</p>
<pre>   The autoaccessor isn't a sub, it just behaves as if it were.
   This is the central point of autoaccessors.  The idea is that
   they should be faster then a method call, because you never
   change scope.  </pre>
<p>Bingo. So, implementationally, it seems all of these could be satisfied
by having this:</p>
<pre>   $r-&gt;method;</pre>
<p>Do the following in order:</p>
<pre>   1. Look for a declared autoaccessor for the given context,
      context of course being where $r is.

   2. Look for a class method (same as currently).</pre>
<p>A quick lookup in some type of centrally-maintained hash or something
should do the trick.</p>
<a name='EXAMPLES'></a><h1>EXAMPLES</h1>
<p>This example shows how much easier it would have been to write the
example on line 170 of perltoot.pod:</p>
<pre>    package Person;
    use strict;
    
    ##################################################
    ## the object constructor (simplistic version)  ##
    ##################################################
    sub new {
        my $self  = {};
        $self-&gt;{name}  :laccess :raccess = undef;
        $self-&gt;{age}   :laccess :raccess = undef;
        $self-&gt;{peers} :laccess :raccess = [];
        return bless $self; 
    }</pre>
<p>Note the lack of anything close to the next 15 lines of code; all of
that is taken care of with the simple attribute settings above.</p>
<a name='MIGRATION'></a><h1>MIGRATION</h1>
<p>None. New functionality.</p>
<a name='NOTES'></a><h1>NOTES</h1>
<p>I ripped the guts out of the original RFC in an attempt to simplify
things and get the concepts out there. However, a few things were lost
in the process:</p>
<pre>   1. automatic dereferencing of return values
   2. readonly rvalue subs
   3. mutators</pre>
<p>I suspect the first one should not be solved. The real idea behind
autoaccessors, as James pointed out, is speed and simplicity. As such,
requiring you to pass stuff around by reference:</p>
<pre>   $r-&gt;autoaccessor = \@stuff;
   $r-&gt;autoaccessor(\@stuff);
   @stuff = @{$r-&gt;autoaccessor};</pre>
<p>Is probably not such a bad idea, since references are faster anyways,
and this greatly simplifies what the autoaccessors have to do.</p>
<p>As for the second one, perhaps making the <code>:raccess</code> tag a simple
accessor, unable to handle assignment (as noted below in the archives),
is really what should be done. This gives us back readonly <code>rvalue</code>
subs, plus you can always use <code>:laccess</code> to create an <code>lvalue</code> sub for
assignment (which is probably cleaner anyways). I suspect this may be
the correct approach.</p>
<p>As for mutators, I suspect that most of the important functions should
be able to be handled by the separation and combination of the
<code>:laccess</code> and <code>:raccess</code> attributes, but feel free to point out if
this is completely wrong. :-)</p>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<p>RFC 279: my() syntax extensions and attribute declarations</p>
<p>RFC 337: Common attribute system to allow user-defined, extensible attributes</p>
<p><a href='http://www.mail-archive.com/perl6-language-objects@perl.org/msg00417.html' target='_blank'>www.mail-archive.com</a></p>
<p><a href='http://www.mail-archive.com/perl6-language-objects@perl.org/msg00418.html' target='_blank'>www.mail-archive.com</a></p>
<p><a href='http://www.mail-archive.com/perl6-language-objects@perl.org/msg00098.html' target='_blank'>www.mail-archive.com</a></p>
<p><a href='http://www.mail-archive.com/perl6-language-objects@perl.org/msg00099.html' target='_blank'>www.mail-archive.com</a></p>
</div>
